﻿using System;
using System.IO;
using System.Collections;
using System.Web;
using System.Reflection;
using System.Web.Configuration;

namespace SystemX.Web
{
    public static partial class Utils
    {
        /// <summary>
        /// This method returns all code assemblies in app_code
        /// If app_code has subdirectories for c#, vb.net etc
        /// Each one will come back as a separate assembly
        /// So we can support extensions in multiple languages
        /// </summary>
        /// <returns>List of code assemblies</returns>
        public static ArrayList CodeAssemblies(string assemblyCfgName)
        {
            ArrayList codeAssemblies = new ArrayList();
            CompilationSection s = null;
            try
            {
                string assemblyName = "__code";
                try
                {
                    s = (CompilationSection)WebConfigurationManager.GetSection("system.web/compilation");
                }
                catch (System.Security.SecurityException)
                {
                    // No read permissions on web.config due to the trust level (must be High or Full)
                }

                if (s != null && s.CodeSubDirectories != null && s.CodeSubDirectories.Count > 0)
                {
                    for (int i = 0; i < s.CodeSubDirectories.Count; i++)
                    {
                        assemblyName = String.Format("App_SubCode_{0}", s.CodeSubDirectories[i].DirectoryName);
                        codeAssemblies.Add(Assembly.Load(assemblyName));
                    }
                }
                else
                {
                    Type t = Type.GetType("Mono.Runtime");
                    if (t != null) assemblyName = "App_Code";
                    codeAssemblies.Add(Assembly.Load(assemblyName));
                }

                GetCompiledExtensions(codeAssemblies, assemblyCfgName);
            }
            catch (System.IO.FileNotFoundException) {/*ignore - code directory has no files*/}

            return codeAssemblies;
        }
        /// <summary>
        /// To support compiled extensions
        /// This methed looks for DLLs in the "/bin" folder
        /// and if assembly compiled with configuration
        /// attributed set to "CoyoEdenExtension" it will
        /// be added to the list of code assemlies
        /// </summary>
        /// <param name="assemblies">List of code assemblies</param>
        private static void GetCompiledExtensions(ArrayList assemblies, string assemblyCfgName)
        {
            string s = Path.Combine(HttpContext.Current.Server.MapPath("~/"), "bin");
            string[] fileEntries = Directory.GetFiles(s);
            foreach (string fileName in fileEntries)
            {
                if (fileName.EndsWith(".dll", StringComparison.OrdinalIgnoreCase))
                {
                    Assembly asm = Assembly.LoadFrom(fileName);
                    object[] attr = asm.GetCustomAttributes(typeof(AssemblyConfigurationAttribute), false);
                    if (attr != null && attr.Length > 0)
                    {
                        AssemblyConfigurationAttribute aca = (AssemblyConfigurationAttribute)attr[0];
                        if (aca != null && aca.Configuration == assemblyCfgName)//E.g,CoyoEdenExtension
                        {
                            assemblies.Add(asm);
                        }
                    }
                }
            }
        }
    }
}
